/*******************************************************************************
 * Copyright 2011-2012 Dik Grapendaal
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package sh.grapendaal.tsuushin.core;

import java.io.IOException;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;


/**
 * This class serves as a layer of abstraction between socket logic and the bot.
 * This allows the bot to concentrate on processing the messages and this class
 * on the actual socket processing.
 */
public class IrcClient {
	private ClientBootstrap bootstrap;
	private Network network;
	private Channel channel;
	private ChannelFuture lastWriteFuture;

	/**
	 * Sets up this client with the given bootstrap and server.
	 * 
	 * @param bootstrap
	 *            The client bootstrap to use.
	 * @param server
	 *            The server to connect to.
	 */
	public IrcClient(ClientBootstrap bootstrap, Network network) {
		this.bootstrap = bootstrap;
		this.network = network;
		this.channel = null;
	}

	/**
	 * Connects to the setup server.
	 * 
	 * @throws IOException
	 *             If we couldn't connect.
	 */
	public void connect() throws IOException {
		ChannelFuture future = bootstrap.connect(network.getServers().iterator().next());
		channel = future.awaitUninterruptibly().getChannel();
		if (!future.isSuccess()) {
			close();
			throw new IOException(future.getCause());
		}
	}

	/**
	 * Sends a message to the server.
	 * 
	 * @param message
	 *            The message to send.
	 */
	public void send(String message) {
		lastWriteFuture = channel.write(message + "\r\n");
	}

	/**
	 * Closes this client. This blocks until the channel is completely closed.
	 */
	public void close() {
		channel.disconnect();

		channel.getCloseFuture().awaitUninterruptibly();

		if (lastWriteFuture != null) {
			lastWriteFuture.awaitUninterruptibly();
		}

		channel.close().awaitUninterruptibly();
	}
}